package org.javahispano.javacup.tacticas_aceptadas.camigonz.org.icesoft.javacup;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoGolpearBalon;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.JugadorDetalle;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;
import org.javahispano.javacup.modelo.TacticaDetalle;

public class CTeamBaseTactica {

	protected TacticaDetalle detalle = new CTeamTacticaDetalle();

	protected Posicion ball;

	protected double ballHeight;

	protected Posicion lastBall;

	protected double lastBallHeight;

	protected double dx;

	protected double dy;

	protected double dz;

	protected Posicion[] players;

	protected Posicion[] enemies;

	protected boolean initialized;

	protected JugadorDetalle[] playerDetails;

	protected JugadorDetalle[] enemyDetails;

	protected final int MAX_PREDICTION_STEPS = 30;

	protected Posicion[] ballPredictions = new Posicion[MAX_PREDICTION_STEPS];

	protected double[] ballHeightPredictions = new double[MAX_PREDICTION_STEPS];

	protected List<Comando> com = new ArrayList<Comando>();

	protected SituacionPartido sp;

	protected Posicion[] selectedAlignment;

	protected int playerSteps[] = new int[11];

	protected int enemySteps[] = new int[11];

	protected int closestPlayers[] = new int[11];

	protected int closestEnemies[] = new int[11];

	protected int closestEnemiesGoal[] = new int[11];

	protected double ballPlayerDistance[] = new double[11];

	protected double ballEnemyDistance[] = new double[11];

	protected boolean myBall;

	protected boolean unknownBall;

	protected boolean enemyBall;

	protected Map<Integer, Posicion> moveMap = new TreeMap<Integer, Posicion>();

	protected List<Player> playersList;

	protected int assignments[] = new int[11];

	protected int enemyKeeper;

	Player[] p = new Player[11];

	protected Random rnd = new Random();

	protected double ballDx;

	protected double ballDy;

	protected double ballDz;

	protected int defensePlayers;

	protected void update(SituacionPartido sp) {
		if (!initialized) {
			playerDetails = sp.detalleMisJugadores();
			enemyDetails = sp.detalleJugadoresRivales();

			playersList = new ArrayList<Player>();
			for (int i = 0; i < 11; i++) {
				p[i] = new Player(p);
				p[i].setIndex(i);
				p[i].setDetail(playerDetails[i]);
				playersList.add(p[i]);

				if (enemyDetails[i].esPortero()) {
					enemyKeeper = i;
				}
			}
			initialized = true;
		}

		this.sp = sp;
		com.clear();
		moveMap.clear();

		for (int i = 0; i < MAX_PREDICTION_STEPS; i++) {
			ballPredictions[i] = null;
			ballHeightPredictions[i] = -1.0d;
		}

		ball = sp.balon();
		ballHeight = sp.alturaBalon();
		players = sp.misJugadores();
		enemies = sp.rivales();

		if (lastBall == null) {
			lastBall = ball;
			lastBallHeight = 0.0;
		}

		doPredictions();

		closestEnemiesGoal = Constantes.centroArcoInf.indicesMasCercanos(enemies);

		for (int i = 0; i < 11; i++) {
			playerSteps[i] = stepsToBallPlayer(i, MAX_PREDICTION_STEPS);
			enemySteps[i] = stepsToBallEnemy(i, MAX_PREDICTION_STEPS);
			closestEnemies[i] = i;
			closestPlayers[i] = i;
			p[i].setBall(sp.balon());
			p[i].setBallHeight(sp.alturaBalon());
			p[i].setPos(players[i]);
			p[i].setSp(sp);
			ballPlayerDistance[i] = ball.distancia(players[i]);
			ballEnemyDistance[i] = ball.distancia(enemies[i]);
		}

		int t;
		for (int i = 0; i < 10; i++) {
			for (int j = i + 1; j < 11; j++) {
				if (playerSteps[closestPlayers[j]] < playerSteps[closestPlayers[i]]) {
					t = closestPlayers[j];
					closestPlayers[j] = closestPlayers[i];
					closestPlayers[i] = t;
				} else if (playerSteps[closestPlayers[j]] == playerSteps[closestPlayers[i]]) {
					if (ballPlayerDistance[closestPlayers[j]] < ballPlayerDistance[closestPlayers[i]]) {
						t = closestPlayers[j];
						closestPlayers[j] = closestPlayers[i];
						closestPlayers[i] = t;
					}
				}

				if (enemySteps[closestEnemies[j]] < enemySteps[closestEnemies[i]]) {
					t = closestEnemies[j];
					closestEnemies[j] = closestEnemies[i];
					closestEnemies[i] = t;
				} else if (enemySteps[closestEnemies[j]] == enemySteps[closestEnemies[i]]) {
					if (ballEnemyDistance[closestEnemies[j]] < ballEnemyDistance[closestEnemies[i]]) {
						t = closestEnemies[j];
						closestEnemies[j] = closestEnemies[i];
						closestEnemies[i] = t;
					}
				}
			}
		}

		myBall = sp.saco()
				|| sp.puedenRematar().length > 0
				|| playerSteps[closestPlayers[0]] < enemySteps[closestEnemies[0]]
				|| (playerSteps[closestPlayers[0]] == enemySteps[closestEnemies[0]] && ballPlayerDistance[closestPlayers[0]] <= ballEnemyDistance[closestEnemies[0]]);

		enemyBall = sp.sacaRival()
				|| sp.puedenRematarRival().length > 0
				|| enemySteps[closestEnemies[0]] < playerSteps[closestPlayers[0]]
				|| (playerSteps[closestPlayers[0]] == enemySteps[closestEnemies[0]] && ballPlayerDistance[closestPlayers[0]] >= ballEnemyDistance[closestEnemies[0]]);

		unknownBall = (!sp.saco() && !sp.sacaRival())
				&& ((playerSteps[closestPlayers[0]] > 10 && enemySteps[closestPlayers[0]] > 10) || (ballPlayerDistance[closestPlayers[0]] > 7.0 && ballEnemyDistance[closestEnemies[0]] > 7.0));

		for (Player p1 : p) {
			p1.setTeamBall(myBall);
		}
	}

	protected void updateLast() {
		lastBall = ball;
		lastBallHeight = ballHeight;

		for (int i = 0; i < 11; i++) {
			Posicion p = moveMap.get(i);
			double d = ball.distancia(p);
			if (i >= 9 && d >= 25.0) {
				double a = ball.angulo(p);
				p = ball.moverAngulo(a, 25.0);
			}
			if (p != null) {
				com.add(new ComandoIrA(i, p));
			}
		}

		if (sp.puedenRematar().length > 0) {
			boolean shoot = false;
			for (Comando c : com) {
				if (c instanceof ComandoGolpearBalon) {
					shoot = true;
					break;
				}
			}

			if (!shoot) {
				// println("Shot not taken");
				com.add(new ComandoGolpearBalon(sp.puedenRematar()[0], Constantes.centroArcoSup,
						1.0, 0.0));
			}
		}
	}

	protected int stepsToBallPlayer(int idx, int maxSteps) {
		double speed = Constantes.getVelocidad(playerDetails[idx].getVelocidad());
		return stepsToBall(players[idx], speed, maxSteps, playerDetails[idx].esPortero());
	}

	protected int stepsToBallEnemy(int idx, int maxSteps) {
		double speed = Constantes.getVelocidad(enemyDetails[idx].getVelocidad());
		return stepsToBall(enemies[idx], speed, maxSteps, enemyDetails[idx].esPortero());
	}

	private int stepsToBall(Posicion pos, double speed, int maxSteps, boolean keeper) {
		double lastDist = pos.distancia(ball) + 3.0;
		int besti = maxSteps - 1;
		double maxHeight = keeper ? 3.0001 : Constantes.ALTURA_CONTROL_BALON;
		double maxDist = keeper ? Constantes.DISTANCIA_CONTROL_BALON_PORTERO
				: Constantes.DISTANCIA_CONTROL_BALON;
		for (int i = 0; i < maxSteps; i++) {
			Posicion predBall = ballPredictions[i];
			Posicion p = getPlayerPosition(pos, pos.angulo(predBall), speed, i);

			double dist = p.distancia(predBall);

			if (dist < lastDist && ballHeightPredictions[i] <= maxHeight + 0.0001) {
				lastDist = dist;
				besti = i;
				if (dist < maxDist) {
					return i;
				}
			}
		}
		return besti;
	}

	private void doPredictions() {
		ballDx = dx = ball.getX() - lastBall.getX();
		ballDy = dy = ball.getY() - lastBall.getY();
		dz = ballHeight - lastBallHeight;
		ballDz = dz = Math.round(dz / Constantes.G) * Constantes.G;
		for (int i = 0; i < MAX_PREDICTION_STEPS; i++) {
			predictBall(i);
			predictBallHeight(i);
		}
	}

	protected Posicion predictBall(int steps) {
		if (steps < 0)
			steps = 0;
		if (ballPredictions[steps] != null)
			return ballPredictions[steps];
		double factor = Constantes.FACTOR_DISMINUCION_VEL_BALON_SUELO;
		if (ballHeight >= 0.00001) {
			factor = Constantes.FACTOR_DISMINUCION_VEL_BALON_AIRE;
		}
		double s = ((1.0 - Math.pow(factor, steps + 1)) / (1.0 - factor)) - 1.0;
		double x = ball.getX() + dx * s;
		double y = ball.getY() + dy * s;
		ballPredictions[steps] = new Posicion(x, y);
		return ballPredictions[steps];
	}

	protected double predictBallHeight(int steps) {
		if (steps < 0) {
			ballHeightPredictions[0] = ballHeight;
			return lastBallHeight;
		} else if (steps == 0) {
			ballHeightPredictions[0] = ballHeight;
			return ballHeight;
		}
		if (ballHeightPredictions[steps] > -0.001) {
			return ballHeightPredictions[steps];
		}
		if (ballHeightPredictions[steps - 1] < -0.001) {
			predictBallHeight(steps - 1);
		}
		double dzt = 0.0;
		double lzt = 0.0;
		if (steps == 1) {
			lzt = ballHeight;
			dzt = lzt - lastBallHeight;
		} else if (steps > 1) {
			lzt = ballHeightPredictions[steps - 1];
			dzt = lzt - ballHeightPredictions[steps - 2];
		}
		dzt = dzt - Constantes.G;
		dzt = Math.round(dzt / Constantes.G) * Constantes.G;
		if (ballHeight == 0.0) {
			dzt = (-dzt - Constantes.G) * Constantes.FACTOR_DISMINUCION_ALTURA_BALON_REBOTE;
			dzt = Math.round(dzt / Constantes.G) * Constantes.G;
		}
		double z = lzt + dzt;
		z = Math.round(z / Constantes.G) * Constantes.G;
		ballHeightPredictions[steps] = z;
		return ballHeightPredictions[steps];
	}

	protected Posicion getPlayerPosition(Posicion p, double a, double speed, int steps) {
		return p.moverAngulo(a, speed * steps);
	}

	protected void alignPlayers() {
		int a = alignmentY.length - 1;
		if (sp.saco()) {
			if (ball.getY() < 0.0) {
				a = 2;
			} else {
				a = 4;
			}
		} else {
			for (int i = 0; i < alignmentY.length - 1; i++) {
				if (ball.getY() < alignmentY[i]) {
					a = i;
					break;
				}
			}
		}
		if (myBall && ball.getY() > -5.0) {
			a = Math.min(a + 1, alignmentY.length - 1);
		}

		selectedAlignment = alignments[a];
		for (int i = 0; i < 11; i++) {
			p[i].setState(7);
			p[i].setAlign(selectedAlignment[i]);
			moveMap.put(i, selectedAlignment[i]);
		}
	}

	protected int checkClear(Posicion p1, Posicion p2, double speed) {
		double maxd = 10000.0;
		int best = -1;
		for (int i = 0; i < 11; i++) {
			if (dot(p2, p1, enemies[i]) > 0) {
				continue;
			}

			// Minus 1.0 due to the reach of the ball by a player
			double d2 = p1.distancia(enemies[i]);
			double a = enemies[i].angulo(p1);
			double d3 = linePointDistance(p1, p2, enemies[i], true);
			double d4 = Math.abs(d3 * Math.sin(a));
			d4 = Math.max(d4 - 1.0, 0.5);

			double it = Math.ceil(d4 / Constantes.REMATE_VELOCIDAD_MAX) + 3.0;
			double maxPath = it * Constantes.getVelocidad(enemyDetails[i].getVelocidad());
			if (d4 <= maxPath || (d3 <= Constantes.DISTANCIA_CONTROL_BALON)) {
				if (d2 < maxd) {
					best = i;
					maxd = d2;
				}
			}
		}
		return best;
	}

	protected int checkClear(Posicion p1, Posicion p2) {
		return checkClear(p1, p2, 0.0);
	}

	// Dot Product between P1P2 and P2P3
	protected double dot(Posicion p1, Posicion p2, Posicion p3) {
		double[] ab = new double[2];
		double[] bc = new double[2];
		ab[0] = p2.getX() - p1.getX();
		ab[1] = p2.getY() - p1.getY();
		bc[0] = p3.getX() - p2.getX();
		bc[1] = p3.getY() - p2.getY();
		double dot = ab[0] * bc[0] + ab[1] * bc[1];
		return dot;
	}

	// Compute the cross product AB x AC
	protected double cross(Posicion p1, Posicion p2, Posicion p3) {
		double[] ab = new double[2];
		double[] ac = new double[2];
		ab[0] = p2.getX() - p1.getX();
		ab[1] = p2.getY() - p1.getY();
		ac[0] = p3.getX() - p1.getX();
		ac[1] = p3.getY() - p1.getY();
		double cross = ab[0] * ac[1] - ab[1] * ac[0];
		return cross;
	}

	protected double distance(Posicion a, Posicion b) {
		double d1 = a.getX() - b.getX();
		double d2 = a.getY() - b.getY();
		return Math.sqrt(d1 * d1 + d2 * d2);
	}

	// Distance from AB to C
	protected double linePointDistance(Posicion a, Posicion b, Posicion c, boolean seg) {
		double dist = cross(a, b, c) / distance(a, b);
		if (seg) {
			double d1 = dot(a, b, c);
			if (d1 > 0) {
				return distance(b, c);
			}
			double d2 = dot(b, a, c);
			if (d2 > 0) {
				return distance(a, c);
			}
		}
		return Math.abs(dist);
	}

	// Checks if C is between AB
	protected boolean linePointInSegment(Posicion a, Posicion b, Posicion c) {
		double d1 = dot(a, b, c);
		if (d1 > 0) {
			return false;
		}
		double d2 = dot(b, a, c);
		if (d2 > 0) {
			return false;
		}
		return true;
	}

	/**
	 * <p>
	 * Returns true if a-b<=max, false otherwise
	 * </p>
	 * 
	 * @param a
	 * @param b
	 * @param max
	 * @return
	 */
	protected boolean angleDiference(double a, double b, double max) {
		if (angleDiference(a, b) <= max) {
			return true;
		}
		return false;
	}

	protected double angleDiference(double a, double b) {
		if (Math.abs(a - b) >= Math.PI) {
			double t = Math.max(a, b);
			b = Math.min(a, b) + Math.PI * 2.0;
			a = t;
		}
		return Math.abs(a - b);
	}

	protected void keeper() {
		if (ball.getY() >= -10.0) {
			moveMap.put(0, new Posicion(Constantes.centroArcoInf.getX(), Constantes.centroArcoInf
					.getY()));
			return;
		}
		double dist1 = linePointDistance(ball, Constantes.posteDerArcoInf, players[0], true);
		double dist2 = linePointDistance(ball, Constantes.posteIzqArcoInf, players[0], true);
		if (dist1 < dist2) {
			dist1 = dist1 * Math.abs(Math.cos(players[0].angulo(ball) - Math.PI / 2.0));
		} else {
			dist2 = dist2 * Math.abs(Math.cos(players[0].angulo(ball) + Math.PI / 2.0));
		}
		double dif = dist1 - dist2;
		if (Math.abs(dif) <= 0.125) {
			moveMap.put(0, players[0]);
			return;
		}
		double x = players[0].getX() + dif / 2.0;
		x = Math.max(x, Constantes.posteIzqArcoInf.getX() + 0.25);
		x = Math.min(x, Constantes.posteDerArcoInf.getX() - 0.25);
		moveMap.put(0, new Posicion(x, Constantes.centroArcoInf.getY()));
	}

	Posicion alineacion1[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-23.062937062937063, -32.07013574660634),
			new Posicion(-6.6573426573426575, -35.39592760180996),
			new Posicion(7.132867132867133, -36.10859728506787),
			new Posicion(23.062937062937063, -32.54524886877828),
			new Posicion(0.23776223776223776, -23.28054298642534),
			new Posicion(-17.356643356643357, -15.91628959276018),
			new Posicion(17.356643356643357, -16.153846153846153),
			new Posicion(0.23776223776223776, -10.452488687782806),
			new Posicion(-20.447552447552447, -0.23755656108597287),
			new Posicion(21.636363636363637, -1.1877828054298643) };

	Posicion alineacion2[] = new Posicion[] {
			new Posicion(-0.23776223776223776, -46.56108597285068),
			new Posicion(-23.3006993006993, -21.61764705882353),
			new Posicion(-6.181818181818182, -26.131221719457013),
			new Posicion(7.846153846153847, -26.131221719457013),
			new Posicion(23.3006993006993, -21.855203619909503),
			new Posicion(-0.23776223776223776, -8.789592760180994),
			new Posicion(-22.825174825174827, -1.900452488687783),
			new Posicion(20.923076923076923, -1.1877828054298643),
			new Posicion(-9.748251748251748, -0.7126696832579186),
			new Posicion(0.0, -1.1877828054298643),
			new Posicion(5.468531468531468, -1.900452488687783) };

	Posicion alineacione[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-23.538461538461537, -46.334841628959275),
			new Posicion(-6.6573426573426575, -48.522624434389144),
			new Posicion(6.895104895104895, -48.522624434389144),
			new Posicion(22.825174825174827, -46.43438914027149),
			new Posicion(-15.804195804195804, -50.744343891402718),
			new Posicion(-7.2, -50.31900452488688), new Posicion(7.2, -50.744343891402718),
			new Posicion(15.706293706293707, -50.457013574660635),
			new Posicion(-0.23776223776223776, -37.77149321266968),
			new Posicion(4.9930069930069925, -16.866515837104075) };

	Posicion alineacionp[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-23.538461538461537, -46.334841628959275),
			new Posicion(-6.6573426573426575, -48.522624434389144),
			new Posicion(6.895104895104895, -48.522624434389144),
			new Posicion(22.825174825174827, -46.43438914027149),
			new Posicion(-3.804195804195804, -42.744343891402718),
			new Posicion(-19.496503496503497, -44.31900452488688),
			new Posicion(21.874125874125873, -44.744343891402718),
			new Posicion(5.706293706293707, -42.457013574660635),
			new Posicion(-0.23776223776223776, -37.77149321266968),
			new Posicion(4.9930069930069925, -16.866515837104075) };

	Posicion alineaciond[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-23.538461538461537, -44.334841628959275),
			new Posicion(-6.6573426573426575, -46.522624434389144),
			new Posicion(6.895104895104895, -46.522624434389144),
			new Posicion(22.825174825174827, -44.43438914027149),
			new Posicion(-3.804195804195804, -37.744343891402718),
			new Posicion(-19.496503496503497, -38.31900452488688),
			new Posicion(21.874125874125873, -38.744343891402718),
			new Posicion(5.706293706293707, -37.457013574660635),
			new Posicion(-0.23776223776223776, -37.77149321266968),
			new Posicion(4.9930069930069925, -16.866515837104075) };

	Posicion alineacion3[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-23.538461538461537, -41.334841628959275),
			new Posicion(-6.6573426573426575, -42.522624434389144),
			new Posicion(6.895104895104895, -42.522624434389144),
			new Posicion(22.825174825174827, -39.43438914027149),
			new Posicion(-3.804195804195804, -28.744343891402718),
			new Posicion(-19.496503496503497, -27.31900452488688),
			new Posicion(21.874125874125873, -28.744343891402718),
			new Posicion(5.706293706293707, -29.457013574660635),
			new Posicion(-6.895104895104895, -8.789592760180994),
			new Posicion(4.9930069930069925, -16.866515837104075) };

	Posicion alineacion4[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-23.062937062937063, -32.07013574660634),
			new Posicion(-6.6573426573426575, -35.39592760180996),
			new Posicion(7.132867132867133, -36.10859728506787),
			new Posicion(23.062937062937063, -32.54524886877828),
			new Posicion(-3.5664335664335667, -21.380090497737555),
			new Posicion(-19.97202797202797, -21.142533936651585),
			new Posicion(20.685314685314687, -22.330316742081447),
			new Posicion(4.755244755244756, -22.092760180995477),
			new Posicion(-6.895104895104895, -8.789592760180994),
			new Posicion(8.55944055944056, -3.3257918552036196) };

	Posicion alineacion5[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-24.013986013986013, -21.142533936651585),
			new Posicion(-7.132867132867133, -24.230769230769234),
			new Posicion(7.132867132867133, -24.705882352941178),
			new Posicion(22.11188811188811, -20.192307692307693),
			new Posicion(-0.4755244755244755, -0.9502262443438915),
			new Posicion(-19.97202797202797, 11.877828054298643),
			new Posicion(19.25874125874126, 10.690045248868778),
			new Posicion(-1.188811188811189, 16.391402714932127),
			new Posicion(-9.510489510489512, 25.418552036199095),
			new Posicion(9.986013986013985, 33.73303167420815) };

	Posicion alineacion6[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-23.538461538461537, -6.889140271493213),
			new Posicion(-5.706293706293707, -18.766968325791854),
			new Posicion(6.181818181818182, -19.004524886877828),
			new Posicion(20.685314685314687, -6.651583710407239),
			new Posicion(5.706293706293707, -2.6131221719457014),
			new Posicion(-22.11188811188811, 19.004524886877828),
			new Posicion(19.734265734265733, 17.816742081447966),
			new Posicion(-3.804195804195804, -1.4253393665158371),
			new Posicion(-11.65034965034965, 35.63348416289593),
			new Posicion(4.5174825174825175, 41.0972850678733) };

	Posicion alineacion7[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-21.3986013986014, 7.601809954751132),
			new Posicion(-9.272727272727272, -8.314479638009049),
			new Posicion(9.510489510489512, -8.789592760180994),
			new Posicion(19.97202797202797, 9.739819004524888),
			new Posicion(6.181818181818182, 19.004524886877828),
			new Posicion(-18.78321678321678, 28.744343891402718),
			new Posicion(17.11888111888112, 27.31900452488688),
			new Posicion(-4.9930069930069925, 19.95475113122172),
			new Posicion(-11.65034965034965, 35.63348416289593),
			new Posicion(2.377622377622378, 41.57239819004525) };

	Posicion alineacion8[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-18.307692307692307, 13.540723981900454),
			new Posicion(-9.272727272727272, 5.701357466063349),
			new Posicion(8.55944055944056, 4.98868778280543),
			new Posicion(19.496503496503497, 14.015837104072398),
			new Posicion(7.846153846153847, 19.95475113122172),
			new Posicion(-20.20979020979021, 25.893665158371043),
			new Posicion(18.78321678321678, 25.18099547511312),
			new Posicion(-2.8531468531468533, 19.95475113122172),
			new Posicion(-6.895104895104895, 41.80995475113122),
			new Posicion(6.895104895104895, 41.57239819004525) };

	Posicion[][] alignments = { alineacione, alineacionp, alineaciond, alineacion3, alineacion4,
			alineacion5, alineacion6, alineacion8 };

	double alignmentY[] = { -40, -30.0, -23.0, -18.0, 0.0, 18.0, 35.0, 100.0 };

	public TacticaDetalle getDetalle() {
		return detalle;
	}

	public Posicion[] getPosicionSaca(SituacionPartido sp) {
		return alineacion2;
	}

	public Posicion[] getPosicionRecive(SituacionPartido sp) {
		return alineacion1;
	}

	protected int passCount = 0;

	protected double distanceToBall[] = new double[11];

	protected int enemyInLOP[] = new int[11];

	protected double distanceEnemyInLOP[] = new double[11];

	protected int closeEnemies[] = new int[11];

	protected int closestEnemyP[] = new int[11];

	protected double distanceEnemyP[] = new double[11];

	protected int passCost[][] = new int[11][11];

	protected int passSolution[] = new int[11];

	protected int passMemory[] = new int[11];

	protected boolean goalPossibility[] = new boolean[11];

	protected boolean atLeastOneGoal = false;

	protected void analyzePass() {
		int idx = sp.puedenRematar()[0];

		atLeastOneGoal = false;
		for (int i = 0; i < 11; i++) {
			Posicion p2 = players[i];
			if (i != idx) {
				double d = ballPlayerDistance[i];
				distanceToBall[i] = d;
				enemyInLOP[i] = checkClear(ball, p2, Constantes.getVelocidad(playerDetails[i]
						.getVelocidad()));
				if (enemyInLOP[i] != -1) {
					int idx2 = enemyInLOP[i];
					double d2 = ballEnemyDistance[idx2];
					distanceEnemyInLOP[i] = d2;
				}

				int[] c = p2.indicesMasCercanos(enemies);
				closestEnemyP[i] = c[0];
				distanceEnemyP[i] = p2.distancia(enemies[c[0]]);

				for (int j = 0; j < 11; j++) {
					Posicion p3 = enemies[j];
					double dist = p2.distancia(p3);
					if (dist <= 4.2) {
						closeEnemies[i]++;
					}
				}
			}

			Posicion k = enemies[enemyKeeper];
			double d = p2.distancia(Constantes.centroArcoSup);
			double d1 = linePointDistance(p2, Constantes.posteIzqArcoSup, k, true);
			double d2 = linePointDistance(p2, Constantes.posteDerArcoSup, k, true);
			goalPossibility[i] = false;
			if (d <= 19.0 && (d1 >= 2.1 || d2 >= 2.1)) {
				goalPossibility[i] = true;
				atLeastOneGoal = true;
			}

			for (int j = 0; j < 11; j++) {
				Posicion p3 = players[j];
				double dist = p2.distancia(p3);
				if (i == idx) {
					int lol = 0;
					lol = lol + 1;
				}
				if (i == j) {
					passCost[i][i] = 1000;
				} else {
					if (dist >= 30.0) {
						passCost[i][j] = 5;
						continue;
					}
					int e1 = checkClear(p2, p3.moverPosicion(0.0, 0.6), Constantes
							.getVelocidad(playerDetails[j].getVelocidad()));
					int res = 1000;
					if (e1 == -1) {
						res = 1;
					} else {
						d = p2.distancia(enemies[e1]);
						if (d >= dist * 0.20 && d >= 2.0) {
							res = 5;
						} else {
							res = 10;
						}
					}

					passCost[i][j] = res;
				}
			}
		}

		solvePass();
	}

	private void solvePass() {
		int idx = sp.puedenRematar()[0];
		List<Integer> used = new ArrayList<Integer>();
		List<Integer> unused = new ArrayList<Integer>();
		used.add(idx);

		for (int i = 0; i < 11; i++) {
			unused.add(idx);
			passSolution[i] = passCost[idx][i];
			passMemory[i] = idx;
		}
		unused.remove((Integer) idx);

		while (used.size() < 11) {
			int chosen = -1;
			int cost = 500;
			for (int i : unused) {
				if (passSolution[i] < cost) {
					cost = passSolution[i];
					chosen = i;
				}
			}
			if (chosen == -1) {
				break;
			} else {
				unused.remove((Integer) chosen);
				used.add(chosen);
				for (int i : unused) {
					if (passSolution[i] > passSolution[chosen] + passCost[chosen][i]) {
						passSolution[i] = passSolution[chosen] + passCost[chosen][i];
						passMemory[i] = chosen;
					}
				}
			}
		}
	}

	boolean debug = false;

	protected void println(String x) {
		if (debug) {
			//System.out.println(x);
		}
	}
}